//
//  LineGraphView.m
//  MindView
//
//  Created by NeuroSky on 10/13/11.
//  Copyright 2012. All rights reserved.
//

#import "LineGraphView.h"

@implementation LineGraphView

@synthesize backgroundColor;
@synthesize lineColor;
@synthesize cursorColor;


float numberOfBigBlocks;
float numberOfSmallBlocks;
float bigBlockSize;
float smallBlockSize;
float lineOffset;
float gridScale;


- (id)initWithCoder:(NSCoder *)aDecoder {
    if(self = [super initWithCoder:aDecoder]) {
        [self initialize];
    }    
    return self;
}

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self initialize];
    }    
    return self;
}

- (void)initialize {
    
    xAxisMin = 0;    //seconds
    xAxisMax = 6;    //seconds
    yAxisMin = -3072;
    yAxisMax = 3072;
    dataRate = 512;  //Hz

    lineOffset = 1;
    
    _data = [[NSMutableArray alloc] initWithCapacity:(dataRate * xAxisMax)];
    
    index = 0;

    scaler = CARDIO_SCALER;
    
    dataLock = [[NSLock alloc] init];
       
    redraw = [[NSThread alloc] initWithTarget:self selector:@selector(redrawThread) object:nil];
    [redraw start];
 
    
    if(backgroundColor == nil) {
        backgroundColor = [UIColor clearColor];
        self.backgroundColor = backgroundColor;
    }
    
    lineColor = [UIColor blackColor];
    cursorColor = [UIColor redColor];
    
    cursorEnabled = YES;
    gridEnabled = YES;
    
    
}


- (void)drawRect:(CGRect)clientRect {

    if(gridEnabled) {
        
        numberOfBigBlocks = (xAxisMax / 0.2);
        numberOfSmallBlocks = numberOfBigBlocks * 5;
        bigBlockSize = (self.frame.size.width / numberOfBigBlocks);
        smallBlockSize = bigBlockSize / 5;
        
        //        NSLog(@"big blocks %f",numberOfBigBlocks);
        //      NSLog(@"small blocks %f",numberOfSmallBlocks);
        
        
        // Small Blocks
        smallGrid = [UIBezierPath bezierPath];
        [smallGrid removeAllPoints];
        [smallGrid setLineWidth:0.2];
        
        // Vertical lines
        [smallGrid moveToPoint:[self point2PixelsWithXValue:0.0 yValue:yAxisMax]];
        for (int i = 0; i < numberOfSmallBlocks; i++) {
            [smallGrid addLineToPoint:CGPointMake((i * smallBlockSize), yAxisMin)];
            [smallGrid moveToPoint:CGPointMake((i + 1) * smallBlockSize, yAxisMax)];
        }
        
        // Horizontal lines
        [smallGrid moveToPoint:[self point2PixelsWithXValue:0.0 yValue:yAxisMax + lineOffset]];
        for (int i = 0; i < numberOfSmallBlocks; i++) {
            
            [smallGrid addLineToPoint:CGPointMake(xAxisMin, (i * smallBlockSize) + lineOffset)];
            [smallGrid moveToPoint:CGPointMake(self.frame.size.width, ((i + 1) * smallBlockSize) + lineOffset)];
        }
        
        [[UIColor redColor] set];
        [smallGrid stroke];
        
        // Large blocks
        
        grid = [UIBezierPath bezierPath];
        [grid removeAllPoints];
        [grid setLineWidth:0.3];
        
        // Vertical lines
        [grid moveToPoint:[self point2PixelsWithXValue:0.0 yValue:yAxisMax]];
        for (int i = 0; i < numberOfBigBlocks; i++) {
            [grid addLineToPoint:CGPointMake((i * bigBlockSize), yAxisMin)];
            [grid moveToPoint:CGPointMake((i + 1) * bigBlockSize, yAxisMax)];
        }
        
        // Horizontal lines
        [grid moveToPoint:[self point2PixelsWithXValue:0.0 yValue:yAxisMax + lineOffset]];
        for (int i = 0; i < numberOfBigBlocks; i++) {
            
            [grid addLineToPoint:CGPointMake(xAxisMin, (i * bigBlockSize) + lineOffset)];
            
            [grid moveToPoint:CGPointMake(self.frame.size.width, ((i + 1) * bigBlockSize) + lineOffset)];
        }
        
        [[UIColor redColor] set];
        [grid stroke];
    }
    
    if(_data.count >= 1) {
        
    //    NSLog(@"data %p",_data);
        
        path = [UIBezierPath bezierPath];
        [path removeAllPoints];

        [path setLineWidth:LINE_WIDTH];
        [path moveToPoint:CGPointMake(0, clientRect.size.height/2)];
        
        for(int i = 0; i < index; i++) {
            
                double  value=[[_data objectAtIndex:i] doubleValue];
            
     //       NSLog(@"data object in index %d %p",i, [_data objectAtIndex:i]);
            
                CGPoint tempPixel = [self point2PixelsWithXValue:i
                                                          yValue:(value * scaler)];
                [path addLineToPoint:tempPixel];
            
            
        }
        
        [lineColor set];
        [path stroke];
        
        if(cursorEnabled) {
            cursor = [UIBezierPath bezierPath];
            [cursor removeAllPoints];
            
            [cursor setLineWidth:2];
            [cursor moveToPoint:[self point2PixelsWithXValue:index yValue:yAxisMax]];
            [cursor addLineToPoint:[self point2PixelsWithXValue:index yValue:yAxisMin]];
            [cursorColor set];
            [cursor stroke];
        }
        
        newData = NO;
    }
    
}

- (CGPoint)point2PixelsWithXValue:(double) xValue yValue:(double) yValue {
    CGPoint temp = {0, 0};
    
    temp.x = xValue * self.frame.size.width / (dataRate / DECIMATE * xAxisMax);
    temp.y = ((yValue - yAxisMin) / (yAxisMax - yAxisMin) * self.frame.size.height);

    return temp;
}


- (double)addValue:(double) value {
    
    double addValue = value * -1;

    if (index > dataRate / DECIMATE * xAxisMax - 1) {

        index = 0;
    }  
    
    decimateCount++;
    if (decimateCount < DECIMATE) {
        return addValue;
    } else {
        decimateCount = 0;
    }
    
    [dataLock lock];
    
    if(_data.count <= dataRate / DECIMATE * xAxisMax) {
        
        [_data insertObject:[NSNumber numberWithDouble:addValue ] atIndex:index ];

        
    }else {

        [_data replaceObjectAtIndex:index withObject:[NSNumber numberWithDouble:addValue] ];

    }

    index++;
    [dataLock unlock];
    
    newData = YES;
    
    return addValue;
}

- (void)redrawThread {
    while (true) {
        if (newData) {
            [self performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
        }
        [NSThread sleepForTimeInterval:0.01];
    }
    
}

-(void)cleardata{
    
    [dataLock lock];
    [_data removeAllObjects];
    index = 0;
    [dataLock unlock];    
}



@end
